package com.javatest.springbootcache01.service;

import com.javatest.springbootcache01.bean.Employee;
import com.javatest.springbootcache01.mapper.EmployeeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.*;
import org.springframework.stereotype.Service;

/**
 * @author lzy
 * @version v1.0
 * Create DateTime: 2019/3/21 21:22
 *
 * @CacheConfig抽取缓存的公共配置
 */
@CacheConfig(cacheNames = "emp", cacheManager = "emplyeeCacheManager")
@Service
public class EmployeeService {
    @Autowired
    private EmployeeMapper employeeMapper;

    /**
     * 将方法的运行结果进行缓存，以后再要相同的数据，直接从缓存中获取,不用调用方法
     * <p>
     * CacheMananger管理多个Cache组件，对缓存的真正的CRUD操作在Cache组件中，每一个缓存组件有自己唯一的名字
     *
     * @param id
     * @return
     * @Cacheable几个属性： cacheNames/value:指定缓存组件的名字
     * key:缓存数据使用的key；可以用它来指定。默认是使用方法参数的值 1-方法的返回值
     * 编写SpEL  #id;参数id的值  #a0 #p0 #root.args[0]
     * keyGenerator:key的生成器，可以自己指定key的生成器的组件id
     * key/keyGenerator二选一使用
     * cacheManager:指定缓存管理器；或者使用cacheResolver指定获取解析器
     * condition：指定符合条件的情况下才缓存
     * condition ="#a0>1":第一个参数大于0的时候才进行缓存
     * unless:否定缓存，当unless指定的条件为true，方法的返回值就不会被缓存；可以获取到结果进行判断:
     * e.g:#result==null
     * unless = "#a0==2":如果第一个参数的值是2，结果不缓存
     * sync:是否使用异步模式：异步模式下不支持unless属性
     */
    @Cacheable()
    public Employee getEmp(Integer id) {
        System.out.println("查询" + id + "号员工");
        final Employee emp = employeeMapper.getEmpById(id);
        return emp;
    }

    /**
     * @param employee
     * @return
     * @CachePut:既调用方法，又更新缓存数据；同步更新缓存 修改了数据库的某个数据，同时更新缓存
     * 运行时机：
     * 1.先调用目标方法
     * 2.将目标方法的结果缓存起来
     */
    @CachePut(key = "#employee.id")
    public Employee updateEmp(Employee employee) {
        System.out.println("updateEmp:" + employee);
        employeeMapper.updateEmp(employee);
        return employee;
    }

    /**
     * @param id
     * @CacheEvict:缓存清除 key:指定清除的数据
     * allEntries = true：指定清除这个缓存中所有的数据
     * beforeInvocation默认是false：缓存的清除是否在方法之前执行
     * 默认代表是在方法之后执行
     * 如果当前方法出现异常，如果配置为缓存清除在方法执行之后执行，则这种情况下缓存不会被清空；如果配置为缓存清除在方法执行之前执行，则不论方法是否异常，会先清除缓存
     */
    @CacheEvict(/*key = "#id",*/ allEntries = true)
    public void deleteEmp(Integer id) {
        System.out.println("delete employee:" + id);
//        employeeMapper.deleteEmp(id);
    }

    /**
     * @param lastName
     * @return
     * @Caching 定义复杂的缓存规则
     */
    @Caching(
            cacheable = {@Cacheable(key = "#lastName")},
            put = {
                    @CachePut(key = "#result.id"),
                    @CachePut(key = "#result.email")
            }
    )
    public Employee getEmpByLastName(String lastName) {
        return employeeMapper.getEmpByLastName(lastName);
    }
}
